package com.ecnu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ecnu.common.config.RuoYiConfig;
import com.ecnu.common.constant.Constants;
import com.ecnu.common.constant.HttpStatus;
import com.ecnu.common.core.domain.AjaxResult;
import com.ecnu.common.core.domain.entity.SysDictData;
import com.ecnu.common.core.domain.entity.SysUser;
import com.ecnu.common.core.domain.model.LoginUser;
import com.ecnu.common.core.page.PageDomain;
import com.ecnu.common.core.page.TableDataInfo;
import com.ecnu.common.exception.ServiceException;
import com.ecnu.common.utils.*;
import com.ecnu.common.utils.http.UrlUtils;
import com.ecnu.common.utils.uuid.IdUtils;
import com.ecnu.system.domain.*;
import com.ecnu.system.domain.dto.*;
import com.ecnu.system.domain.vo.*;
import com.ecnu.system.domain.vo.ProjectResultByUserVO;
import com.ecnu.system.domain.vo.statistic.AchievementsStatisticsVO;
import com.ecnu.system.domain.vo.statistic.BarVO;
import com.ecnu.system.domain.vo.statistic.StageUserByMission;
import com.ecnu.system.domain.vo.statistic.UserByStatisticVO;
import com.ecnu.system.mapper.*;
import com.ecnu.system.service.IProjectPlanService;
import com.ecnu.system.service.IProjectStageMissionService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.layout.property.VerticalAlignment;

import java.io.*;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * ecnu_活动_阶段任务表 服务实现类
 * </p>
 *
 * @author zdn
 * @since 2025-03-24
 */
@Service
public class ProjectStageMissionServiceImpl extends ServiceImpl<ProjectStageMissionMapper, ProjectStageMission> implements IProjectStageMissionService {
    @Autowired
    private ProjectStageMissionMapper stageMissionMapper;
    @Autowired
    private ProjectMissionLabelsMapper missionLabelsMapper;
    @Autowired
    private SysDictDataMapper dictDataMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ProjectResultMapper resultMapper;
    @Autowired
    private ProjectUserMapper userMapper;
    @Autowired
    private ProjectTeacherMapper teacherMapper;
    @Autowired
    private ProjectStageUserMapper stageUserMapper;
    @Autowired
    private IProjectPlanService planService;
    @Autowired
    private SysUserMapper sysUserMapper;
@Autowired
    private ProjectExcellentMapper excellentMapper;

    public static final String 横向 = "xAxis";
    public static final String 纵向 = "yAxis";

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 分页查询
     */
    protected void startPage(PageDomain pageDomain) {
        PageUtils.startPage(pageDomain);
    }

    protected String getId() {
        return IdUtils.fastSimpleUUID();
    }

    protected String getUuId() {
        return IdUtils.fastUUID();
    }

    @Override
    public AjaxResult del(String id) {
        ProjectStageMission mission = new ProjectStageMission();
        mission.setId(id);
        mission.setDelFlag("2");
        int i = baseMapper.updateById(mission);
        return AjaxResult.success("删除成功", i);
    }

    @Override
    public AjaxResult infoById(String id, String userId) {
        ProjectStageMission mission = stageMissionMapper.selectById(id);
        if (mission != null) {
            StageMissionVO stageMissionVO = new StageMissionVO();
            BeanUtils.copyProperties(mission, stageMissionVO);
            List<FileLabelsDTO> labelsDTOS = missionLabelsMapper.selectByMissionId(id);
            stageMissionVO.setLabelList(labelsDTOS);
            stageMissionVO.setCheckLists((List<ProjectCheckDTO>) getList(mission.getCheckList()));
            stageMissionVO.setInformations(getList(mission.getInformation()));
            stageMissionVO.setTools(mission.getTool());//原始的 getList(mission.getTool())
            QueryWrapper<ProjectResult> wrapper = new QueryWrapper<>();
            wrapper.eq("pro_id", stageMissionVO.getStageId());
            wrapper.eq("del_flag", "0");
            wrapper.eq("mission_id", id);
            wrapper.eq("create_user", userId);
            List<ProjectResult> list = resultMapper.selectList(wrapper);
            stageMissionVO.setResultList(list);
            //补充学生列表
            List<UserVO> userList =new ArrayList<>();

            QueryWrapper<ProjectStageUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("mission_id",mission.getId())
                    .eq("del_flag", "0")
                    .eq("user_id", "All");
            Long aLong = stageUserMapper.selectCount(queryWrapper);
            //判断是不是全员
            if (aLong == 0) {
                userList = userMapper.getStageUser(mission.getId());
            }else {
                stageMissionVO.setIsAll(true);
            }
            stageMissionVO.setUserList(userList);
            return AjaxResult.success(stageMissionVO);
        }
        return AjaxResult.error("编号错误，未查询到任务");
    }

    /**
     * string ==> object(json方式的）
     *
     * @param mission
     * @return
     */
    public Object getList(String mission) {
        List<Map> checkLists = new ArrayList<>();
        if (StringUtils.isNotBlank(mission)) {
            try {
                mission = mission
                        .replaceAll("^\"+", "")  // 去除开头引号
                        .replaceAll("\"+$", "")
                        .replaceAll("^\"|\"$", "")
                        .replaceAll("\\\\\"", "\"")
                        .replaceAll("\\\\\\\\", "\\\\");
                checkLists = new ObjectMapper().readValue(mission, List.class);
            } catch (JsonProcessingException e) {
                log.error("JSON解析异常", e);
                return mission;
            }
        }
        return checkLists;
    }

    @Override
    public AjaxResult edit(StageMissionDTO dto, LoginUser loginUser) throws JsonProcessingException {
        if (dto.getStartTime() == null || dto.getEndTime() == null) {
            return AjaxResult.error("开始时间和结束时间不能为空");
        }

        // 可选：时间先后顺序校验
        if (dto.getStartTime().after(dto.getEndTime())) {
            return AjaxResult.error("开始时间不能晚于结束时间");
        }

        Project project = projectMapper.selectById(dto.getStageId());
        if (project == null) {
            return AjaxResult.error("活动不存在");
        }
        if (project.getStartTime() != null && dto.getStartTime().before(project.getStartTime())) {
            return AjaxResult.error("任务开始时间不能早于活动开始时间");
        }
        if (project.getEndTime() != null && dto.getEndTime().after(project.getEndTime())) {
            return AjaxResult.error("任务结束时间不能晚于活动结束时间");
        }
        if (StringUtils.isBlank(dto.getId())) {
            return add(dto, loginUser);
        } else {
            return update(dto);
        }
    }

    @Override
    public TableDataInfo listByProId(ProjectResultDTO dto, LoginUser loginUser) {
        try {
            Project project = projectMapper.selectById(dto.getId());
            if (project == null) {
                return OtherUtil.tableError("活动不存在");
            }
            //添加限制，不是教师，不是超管的只能见自己参与的任务
            Long userId = null;
            LambdaQueryWrapper<ProjectTeacher> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ProjectTeacher::getProId, dto.getId());
            wrapper.eq(ProjectTeacher::getTechId, loginUser.getUserId());
            List<ProjectTeacher> projectTeachers = teacherMapper.selectList(wrapper);
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId() != 1L && role.getRoleId() != 2L);
            if ((projectTeachers == null || projectTeachers.isEmpty()) && !isUnauthorizedRole && !project.getCreateUser().equals(String.valueOf(loginUser.getUserId()))) {
                userId = loginUser.getUserId();
            }
            //获取可见的任务
            startPage(dto.getPageDomain());
            List<ProjectStageMission> missions = stageMissionMapper.selectLists(dto, userId);
            TableDataInfo dataTable = OtherUtil.tableSuccess(missions);
            List<ProjectStageMissionVO> copy = OtherUtil.copy(dataTable.getRows(), ProjectStageMissionVO.class);
            if (copy != null && !copy.isEmpty()) {
                dataTable.setRows(copy);
            }
            return dataTable;
        } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException
                e) {
            log.error("查询失败：" + e.getMessage());
            TableDataInfo error = OtherUtil.tableError(e.getMessage());
            return error;
        }
    }

    private AjaxResult update(StageMissionDTO dto) throws JsonProcessingException {
        ProjectStageMission mission = new ProjectStageMission();
        BeanUtils.copyProperties(dto, mission);
        ObjectMapper objectMapper = new ObjectMapper();
        Optional.ofNullable(dto.getCheckLists()).ifPresent(list ->
                list.forEach(checkList -> {
                    if (StringUtils.isBlank(checkList.getId())) {
                        checkList.setId(getId());
                        checkList.setIsSubmit(false);
                    }
                })
        );
        mission.setCheckList(dto.getCheckLists() == null ? "[]" : objectMapper.writeValueAsString(dto.getCheckLists()));//任务清单==>object转成string
        mission.setInformation(dto.getInformations() == null ? "[]" : objectMapper.writeValueAsString(dto.getInformations()));
        mission.setTool(String.valueOf(dto.getTools()));//原始的 dto.getTools() == null ? "[]" : objectMapper.writeValueAsString(dto.getTools())
        mission.setEndTime(OtherUtil.getEndOfDay(dto.getEndTime()));
        int i = stageMissionMapper.updateById(mission);
        if (dto.getLabelList() != null && !dto.getLabelList().isEmpty()) {
            //添加任务标签
            missionAdd(dto, dto.getId());
        }
        //添加任务人员
        missionUserAdd(dto, dto.getId());
        return AjaxResult.success("保存成功", mission.getId());
    }

    private void missionUserAdd(StageMissionDTO dto, String id) {
        stageUserMapper.deleteByFileId(id);
        ArrayList<ProjectStageUser> list = new ArrayList<>();
        if (dto.getIsAll()) {    //判断是不是全员选择
            ProjectStageUser stageUser = new ProjectStageUser();
            stageUser.setId(getId());
            stageUser.setMissionId(id);
            stageUser.setUserId("All");
            stageUser.setProId(dto.getStageId());
            list.add(stageUser);
            stageUserMapper.insert(stageUser);
        } else {
            if (CollectionUtils.isNotEmpty(dto.getUserList())) {
                dto.getUserList().forEach(userVO -> {
                    ProjectStageUser stageUser = new ProjectStageUser();
                    stageUser.setId(getId());
                    stageUser.setMissionId(id);
                    stageUser.setUserId(userVO.getId());
                    stageUser.setUserName(userVO.getUsername());
                    stageUser.setProId(dto.getStageId());
                    list.add(stageUser);
                });
                stageUserMapper.insertBatch(list);
            }
        }

    }

    private AjaxResult add(StageMissionDTO dto, LoginUser loginUser) throws JsonProcessingException {
        ProjectStageMission mission = new ProjectStageMission();
        BeanUtils.copyProperties(dto, mission);
        String id = getId();
        ObjectMapper objectMapper = new ObjectMapper();
        Optional.ofNullable(dto.getCheckLists()).ifPresent(list ->
                list.forEach(checkList -> {
                    checkList.setId(getId());
                    checkList.setIsSubmit(false);
                })
        );
        mission.setCheckList(dto.getCheckLists() == null ? "[]" : objectMapper.writeValueAsString(dto.getCheckLists()));//任务清单==>object转成string
        mission.setInformation(dto.getInformations() == null ? "[]" : objectMapper.writeValueAsString(dto.getInformations()));
        mission.setTool(String.valueOf(dto.getTools()));//原始的 dto.getTools() == null ? "[]" : objectMapper.writeValueAsString(dto.getTools())
        mission.setId(id);
//        mission.setStartTime(dto.getStartTime());
        mission.setEndTime(OtherUtil.getEndOfDay(dto.getEndTime()));
        stageMissionMapper.insert(mission);
        if (dto.getLabelList() != null && !dto.getLabelList().isEmpty()) {
            //添加任务标签
            missionAdd(dto, id);
        }
        //添加任务人员
        missionUserAdd(dto, id);
        //添加到计划中
        this.planAdd(dto, id, loginUser);

        return AjaxResult.success("保存成功", mission.getId());
    }

    private void planAdd(StageMissionDTO dto, String id, LoginUser user) {
        ProjectPlanVO projectPlanVO = new ProjectPlanVO();
        projectPlanVO.setProId(dto.getStageId());
        projectPlanVO.setMissionId(id);
        projectPlanVO.setName(dto.getMissionName());
        projectPlanVO.setDescription(dto.getDescription());
        projectPlanVO.setStartTime(dto.getStartTime());
        projectPlanVO.setEndTime(OtherUtil.getEndOfDay(dto.getEndTime()));

        UserVO userVO = new UserVO();
        userVO.setId(String.valueOf(user.getUserId()));
        userVO.setProId(dto.getStageId());
        userVO.setUsername(user.getUser().getNickName());
        ArrayList<UserVO> projectTeachers = new ArrayList<>();
        projectTeachers.add(userVO);
        projectPlanVO.setTeacherList(projectTeachers);
//
//        AjaxResult edit = planService.edit(projectPlanVO);
        ProjectPlan plan = new ProjectPlan();
        BeanUtils.copyProperties(projectPlanVO, plan);
        plan.setId(id);
        boolean save = planService.save(plan);

        if (projectPlanVO.getTeacherList() != null) {
            extractedTeach(projectPlanVO.getTeacherList(), plan.getId());
        }
    }

    private void extractedTeach(List<UserVO> dto, String planId) {

        teacherMapper.delete(new QueryWrapper<ProjectTeacher>().eq("pro_id", planId));
        if (dto == null || dto.isEmpty()) {
            return;
        }
        teacherMapper.insertBatch(dto.stream()
                .map(user -> {
                    ProjectTeacher teacher = new ProjectTeacher();
                    teacher.setId(getUuId());
                    teacher.setProId(planId);
                    teacher.setTeachName(user.getUsername());
                    teacher.setTechId(user.getId());
                    return teacher;
                })
                .collect(Collectors.toList()));
    }


    private void missionAdd(StageMissionDTO dto, String id) {
        missionLabelsMapper.deleteByFileId(id);
        //获取标签id为空的值
        List<FileLabelsDTO> collect = dto.getLabelList()
                .stream()
                .filter(item -> item.getDictCode() == null)
                .collect(Collectors.toList());
        List<FileLabelsDTO> fileLabelsList = dto.getLabelList()
                .stream()
                .filter(item -> item.getDictCode() != null)
                .collect(Collectors.toList());
        //添加到数据库
        if (!collect.isEmpty()) {
            collect.stream().forEach(item -> {
                SysDictData sysDictData = new SysDictData();
                sysDictData.setDictValue(item.getDictValue());
                sysDictData.setDictLabel(item.getDictValue());
                sysDictData.setDictType("pro_file_label");
                sysDictData.setDictSort(1L);
                sysDictData.setStatus("0");
                sysDictData.setListClass("default");
                dictDataMapper.insertDictData(sysDictData);
                item.setDictCode(sysDictData.getDictCode());
                fileLabelsList.add(item);
            });
        }

        //添加入库
        missionLabelsMapper.insertByFileId(fileLabelsList, id);
    }


    @Override
    public AjaxResult getStatisticList(String id, String proId, LoginUser loginUser) {
        try {
            ProjectStageMission mission = stageMissionMapper.selectById(id);
            if (mission == null) {
                return AjaxResult.error("该任务不存在，请检查id是否正确");
            }

            ObjectMapper objectMapper = new ObjectMapper();
            Long userId = null;
            ProjectUser projectUser = new ProjectUser();
            /**
             * 第一阶段：获取数据库数据
             */
            //取任务清单
            List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                    .stream()
                    .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                    .collect(Collectors.toList());
            //获取报名的信息
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId().equals(1L) || role.getRoleId().equals(2L)
                            || role.getRoleId().equals(103L) || role.getRoleId().equals(101L));
            if (isUnauthorizedRole) {
                projectUser = userMapper.selectOne(new LambdaQueryWrapper<ProjectUser>()
                        .eq(ProjectUser::getUserId, loginUser.getUserId())
                        .eq(ProjectUser::getProId, proId)
                        .eq(ProjectUser::getStatus, "0")
                        .eq(ProjectUser::getDelFlag, "0")
                );
                if (projectUser == null) {
                    throw new ServiceException("您没有权限查看此任务", HttpStatus.NOT_FOUND);
                }
                userId = loginUser.getUserId();
            }

            //获取任务的成果提交量
            List<ProjectResultByUserVO> resultList = resultMapper.selectListByUserOrTeacher(
                    id, proId, userId, projectUser.getTeacherName()
            );
            List<ProjectResultByUserVO> resultList2 = new ArrayList<>(
                    resultList.stream()
                            .collect(
                                    Collectors.toMap(
                                            ProjectResultByUserVO::getTeacherName,
                                            Function.identity(),
                                            (a, b) -> {
                                                Date timeA = a.getCreateTime();
                                                Date timeB = b.getCreateTime();
                                                if (timeA == null) return b;
                                                if (timeB == null) return a;
                                                return timeA.after(timeB) ? a : b; // true 表示 a 更新
                                            }
                                    )
                            )
                            .values()
            );
            //获取任务人员列表
            List<StageUserByMission> userByMissions = stageUserMapper.selectListForList(proId, userId);
            Map<String, List<StageUserByMission>> missionMap = userByMissions.stream()
                    .collect(Collectors.groupingBy(StageUserByMission::getMissionId));
            //获取当前任务的全部人员信息
            Map<String, List<StageUserByMission>> collect = Optional.ofNullable(missionMap.get(id))
                    .filter(CollectionUtils::isNotEmpty)
                    .map(userList -> userList.stream()
                            .collect(Collectors.groupingBy(StageUserByMission::getTeacherName)))
                    .orElse(Collections.emptyMap());

            /**
             * 第二阶段：数据整理
             */
            //1、区分按时完成和逾期完成
            Map<String, List<ProjectResultByUserVO>> resultListMap = Optional.ofNullable(resultList2)
                    .filter(CollectionUtils::isNotEmpty)
                    .map(userList -> userList.stream()
                            .collect(Collectors.groupingBy(ProjectResultByUserVO::getIsPostpone)))
                    .orElse(Collections.emptyMap());
            //2、获取没有提交文件的数据量
            final Integer[] overdue = {0};
            final Integer[] progressDue = {0};
//            if (CollectionUtils.isNotEmpty(collect)) {
            collect.forEach((key, value) -> {
                checkDTOs.forEach(checkDTO -> {
                    long count = resultList2.stream()
                            .filter(result -> result.getStageId().equals(checkDTO.getId())
                                    && result.getTeacherName().equals(key))
                            .count();
                    if (count == 0) {
                        Date date = new Date();
                        Date date1 = DateUtils.parseDate(checkDTO.getEndTime() + " 23:59:59");
                        if (date.after(date1)) {
                            overdue[0]++;
                        } else {
                            progressDue[0]++;
                        }
                    }
                });
            });
//            }
            //写数据
            Integer finishTime = CollectionUtils.isEmpty(resultListMap.get("0")) ? 0 : resultListMap.get("0").size();
            Integer overdueTime = CollectionUtils.isEmpty(resultListMap.get("1")) ? 0 : resultListMap.get("1").size();

            Integer total = (CollectionUtils.isEmpty(checkDTOs) ? 0 : checkDTOs.size()) * (CollectionUtils.isEmpty(collect) ? 0 : collect.size());
            /**
             * 第三阶段：处理数据显示内容
             */
            //创建返回格式
            Map<String, Object> map = new LinkedHashMap<>();
            map = newStatistic(map, null, null, null, null);
//
            map = newStatistic(map, "进行中任务", progressDue[0], getDouble(Double.valueOf(total), Double.valueOf(progressDue[0])), 横向);
            map = newStatistic(map, "逾期任务", overdue[0], getDouble(Double.valueOf(total), Double.valueOf(overdue[0])), 横向);
            map = newStatistic(map, "按时完成", finishTime, getDouble(Double.valueOf(total), Double.valueOf(finishTime)), 横向);
            map = newStatistic(map, "逾期完成", overdueTime, getDouble(Double.valueOf(total), Double.valueOf(overdueTime)), 横向);

            return AjaxResult.success(map);
        } catch (Exception e) {
            log.error("任务概览列表错误：\n" + e.getMessage());
            return AjaxResult.error("数据错误，请联系管理员老师\n" + e.getMessage());
        }
    }

    private <T> List<T> getPrijectList(String list, Class<T> clazz) {
        if (StringUtils.isBlank(list) || list.equals("[]")) {
            return Collections.emptyList();
        }
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(
                    list,
                    objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)
            );
        } catch (JsonProcessingException e) {
            log.error("JSON 解析失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public AjaxResult statisticsOutcome(String id, LoginUser loginUser) {
        BarVO barVO = new BarVO();
        try {
            Long userId = loginUser.getUserId();
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId().equals(1L) || role.getRoleId().equals(2L)
                            || role.getRoleId().equals(103L) || role.getRoleId().equals(101L));
            if (!isUnauthorizedRole) {
                userId = null;
            }
            /**
             * 第一阶段：获取活动下的数据
             */
            ProjectResultDTO dto = new ProjectResultDTO();
            dto.setId(id);
            //取活动下对应用户参与的活动--学生之外是全部
            List<ProjectStageMission> missions = stageMissionMapper.selectLists(dto, userId);
            //根据活动id,取任务对应人员数量
            List<StageUserByMission> userByMissions = stageUserMapper.selectListForList(id, userId);
            //取活动的成果列表
            LambdaQueryWrapper<ProjectResult> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProjectResult::getProId, id);
            queryWrapper.eq(ProjectResult::getDelFlag, "0");
            if (userId != null) {
                queryWrapper.eq(ProjectResult::getCreateUser, userId);
            }
            List<ProjectResult> resultList = resultMapper.selectList(queryWrapper);
            //根据mission_id 分组
            Map<String, List<StageUserByMission>> missionMap = userByMissions.stream()
                    .collect(Collectors.groupingBy(StageUserByMission::getMissionId));
            //根据mission_id 分组
            Map<String, List<ProjectResult>> resultMap = resultList.stream()
                    .collect(Collectors.groupingBy(ProjectResult::getMissionId));
            ObjectMapper objectMapper = new ObjectMapper();

            /**
             * 第二阶段：编排数据
             */
            List<List<Object>> datasetSources = new ArrayList<>();

            // 添加表头
            List<Object> header = new ArrayList<>();
            header.add("任务编号");
            header.add("legends");
            header.add("成果总数");
            header.add("已完成");
            datasetSources.add(header);
//            //添加数据
            missions.forEach(mission -> {
                //取任务清单列表
                List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                        .stream()
                        .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                        .collect(Collectors.toList());
                //根据参与任务的学员进行分组
//                List<StageUserByMission> userByMissions1 = missionMap.get(mission.getId());
                Map<String, List<StageUserByMission>> collect = Optional.ofNullable(missionMap.get(mission.getId()))
                        .filter(CollectionUtils::isNotEmpty)
                        .map(userList -> userList.stream()
                                .collect(Collectors.groupingBy(StageUserByMission::getTeacherName)))
                        .orElse(Collections.emptyMap());
                List<ProjectResult> results = resultMap.get(mission.getId());
                //编排数据
                List<Object> row = new ArrayList<>();
                row.add(mission.getId());
                row.add(mission.getMissionName());  //任务名称
                row.add(checkDTOs.size() * collect.size());//总数
                row.add(CollectionUtils.isEmpty(results) ? 0 : results.size());//提交数
                datasetSources.add(row);
            });

            /**
             * 写入数据
             */
            barVO.setRawData(datasetSources);
        } catch (Exception e) {
            log.error("成果统计错误：\n" + e.getMessage());
            return AjaxResult.error("数据错误，请联系管理员老师\n");
        }
        return AjaxResult.success(barVO);
    }

    @Override
    public AjaxResult selectUserList(LoginUser loginUser, String missionId, String proId, String userId) {
        try {

            //根据用户ID获取用户信息
            ProjectUser projectUser = userMapper.selectOne(new LambdaQueryWrapper<ProjectUser>()
                    .eq(ProjectUser::getUserId, userId)
                    .eq(ProjectUser::getProId, proId)
                    .eq(ProjectUser::getDelFlag, "0")
                    .eq(ProjectUser::getStatus, "0"));
            if (projectUser == null) {
                return AjaxResult.error("用户未参加该活动，如确定已参加，请邮件联系管理员调整");
            }
            //获取当前任务人员表
            List<StageUserByMission> userByMissions = stageUserMapper.selectListForList(proId, null);
            Map<String, List<StageUserByMission>> missionMap = userByMissions.stream()
                    .collect(Collectors.groupingBy(StageUserByMission::getMissionId));
            //获取当前任务的全部人员信息
            Map<String, List<StageUserByMission>> collect = Optional.ofNullable(missionMap.get(missionId))
                    .filter(CollectionUtils::isNotEmpty)
                    .map(userList -> userList.stream()
                            .collect(Collectors.groupingBy(StageUserByMission::getTeacherName)))
                    .orElse(Collections.emptyMap());
            List<StageUserByMission> userByMissions1 = collect.get(
                    StringUtils.isBlank(projectUser.getTeacherName()) ? projectUser.getUserName() : projectUser.getTeacherName());
            if (CollectionUtils.isNotEmpty(userByMissions1)) {
                List<SysUser> sysUsers = sysUserMapper.selectListForUser(
                        userByMissions1.stream()
                                .map(user -> Long.valueOf(user.getUserCode()))
                                .collect(Collectors.toList()));
                List<UserByStatisticVO> copy = OtherUtil.copy(sysUsers, UserByStatisticVO.class);
                return AjaxResult.success(copy);
            } else {
                return AjaxResult.success(new ArrayList<UserByStatisticVO>());
            }
        } catch (Exception e) {
            logger.error("成果完成情况接口--获取用户列表错误\r\n" + e.getMessage());
            return AjaxResult.error("获取用户列表错误,请联系管理员调整");
        }
    }

    @Override
    public AjaxResult infoList(String id, LoginUser loginUser) {
        try {
            Long userId = null;
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId().equals(1L) || role.getRoleId().equals(2L)
                            || role.getRoleId().equals(103L) || role.getRoleId().equals(101L));
            if (isUnauthorizedRole) {
                userId = loginUser.getUserId();
            }
            ProjectResultDTO dto = new ProjectResultDTO();
            dto.setId(id);
            /**
             * 第1步：获取活动任务数量
             */
            //取活动下对应用户参与的活动--学生之外是全部
            List<ProjectStageMission> missions = stageMissionMapper.selectLists(dto, userId);
            //根据活动id,取任务对应人员数量
            List<StageUserByMission> userByMissions = stageUserMapper.selectListForList(id, userId);
            //取活动的成果列表
            LambdaQueryWrapper<ProjectResult> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProjectResult::getProId, id);
            queryWrapper.eq(ProjectResult::getDelFlag, "0");
            if (userId != null) {
                queryWrapper.eq(ProjectResult::getCreateUser, userId);
            }
            List<ProjectResult> resultList = resultMapper.selectList(queryWrapper);
            //根据mission_id 分组
            Map<String, List<StageUserByMission>> missionMap = userByMissions.stream()
                    .collect(Collectors.groupingBy(StageUserByMission::getMissionId));
            //根据mission_id 分组
            Map<String, List<ProjectResult>> resultMap = resultList.stream()
                    .collect(Collectors.groupingBy(ProjectResult::getMissionId));
            ObjectMapper objectMapper = new ObjectMapper();

            /**
             * 第2步：整理数据
             */
            final Integer[] resultCount = {0};
            final Integer[] submittedCount = {0};

            //成果总数计算
            missions.forEach(mission -> {
                //取任务清单列表
                List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                        .stream()
                        .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                        .collect(Collectors.toList());
                //根据参与任务的学员进行分组
                Map<String, List<StageUserByMission>> collect = Optional.ofNullable(missionMap.get(mission.getId()))
                        .filter(CollectionUtils::isNotEmpty)
                        .map(userList -> userList.stream()
                                .collect(Collectors.groupingBy(StageUserByMission::getTeacherName)))
                        .orElse(Collections.emptyMap());
                List<ProjectResult> results = resultMap.get(mission.getId());
                resultCount[0] = resultCount[0] + (checkDTOs.size() * collect.size());//总数
                submittedCount[0] = submittedCount[0] + (CollectionUtils.isEmpty(results) ? 0 : results.size());//已提交数

            });

            /**
             * 第3步：返回结果
             */
            Map<String, Integer> map = new LinkedHashMap<>();
            map.put("任务数", CollectionUtils.isEmpty(missions) ? 0 : missions.size());
            map.put("成果总数", resultCount[0]);
            map.put("已交成果数", submittedCount[0]);
            map.put("未交成果数", resultCount[0] - submittedCount[0]);

            return AjaxResult.success(map);
        } catch (Exception e) {
            log.error("统计顶头有问题：" + e.getMessage());
            return AjaxResult.error("数据有误");
        }
    }

    @Override
    public AjaxResult getCertificate(String proId, LoginUser loginUser) throws IOException {
        try {
            //获取活动内容
//            LambdaQueryWrapper<Project> projectWrapper = new LambdaQueryWrapper<>();
//            projectWrapper.eq(Project::getId, proId)
//                    .eq(Project::getDelFlag, "0");
//            Project project = projectMapper.selectOne(projectWrapper);
//            if (project == null) {
//                return AjaxResult.error("活动不存在或已被删除，请联系管理员调整");
//            }
//            LambdaQueryWrapper<ProjectUser> pUserWrapper = new LambdaQueryWrapper<>();
//            pUserWrapper.eq(ProjectUser::getProId, proId)
//                    .eq(ProjectUser::getUserId, loginUser.getUserId())
//                    .eq(ProjectUser::getDelFlag, "0");
//            ProjectUser projectUser = userMapper.selectOne(pUserWrapper);
//            if (projectUser == null) {
//                return AjaxResult.error("您没有参与该活动,暂无证书");
//            }
            //根据登录人去获取成果和证书--未对接专家送审逻辑--暂未处理

            //处理证书文件（1 获奖，2 参与证明）待处理
            String s="通过.pdf";
            if (1==1) {//未通过的情况
                s = "未通过.pdf";
            }
            LinkedHashMap<String, String> hashMap = new LinkedHashMap<>();
            //添加参数
            hashMap.put("pro_name", "第三届上海市高校 MBA 研学写作大赛");
            hashMap.put("user_name", "朱大年");
            hashMap.put("user_teacher", "XXX");
            //获取证书相对地址
            String src = getResult(s,hashMap);
            //返回相对地址
            return AjaxResult.success(src);
        }catch (Exception e){
            log.error("获取证书错误：" + e.getMessage());
            return AjaxResult.error("获取证书错误");
        }
    }



    /**
     * 获取证书相对地址(需要添加配置)
     * @return
     * @throws IOException
     */
    private String getResult(String 模版地址, LinkedHashMap<String, String> hashMap) throws IOException {
        String src = 模版地址;
        String localPath = RuoYiConfig.getProfile();// 获取项目路径
        String dest = "/template/result/" + hashMap.get("pro_name")+"_"+hashMap.get("user_name")+".pdf";

        String absolutePath = localPath + "/template/" + src;
        String afterPath = localPath + dest;
        File file = new File(absolutePath);

        // 验证文件是否存在
        if (!file.exists()) {
            log.error("文件不存在: " + absolutePath);
            throw new ServiceException("获取证书错误，请联系管理员处理");
        }
        // 打开原始 PDF 并准备写入新内容
        try (InputStream inputStream = new FileInputStream(file)) {
            // 打开原始 PDF 并准备写入新内容
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(inputStream), new PdfWriter(afterPath));
            Document document = new Document(pdfDoc);

            // 创建支持中文的字体
            PdfFont contentFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
            PdfFont 行楷 = PdfFontFactory.createFont(
                    localPath+"/fonts/SanJiXingKaiJianTi-Cu-2.ttf",       // classpath 路径
                    PdfEncodings.IDENTITY_H,    // 必须用 IDENTITY_H 支持中文
                    true                        // 嵌入字体（推荐，避免目标设备无此字体）
            );

            // 设置不同字号
            float titleSize = 36f;
            float contentSize = 18f;
            float smallSize = 14f;

            // 获取页面尺寸
            Rectangle pageSize = pdfDoc.getFirstPage().getPageSize();
            float x = pageSize.getWidth() / 2;           // 水平居中
            float y = pageSize.getHeight() * 0.7f;       // 垂直位置


            // 创建内容段落
            Paragraph 获奖段落 = new Paragraph(
                    "上海理工大学工商管理专业学位\n" +
                            "研究生 "+hashMap.get("user_name")+" 的学位论文荣获")
                    .setFont(contentFont)
                    .setFontSize(contentSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);

            // 创建标题段落
            Paragraph 奖项 = new Paragraph("优秀论文奖")
                    .setFont(行楷)
                    .setFontSize(titleSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);

            // 添加指导教师信息
            Paragraph 指导教师 = new Paragraph(
                    "指导教师：陈德智\n" +
                            "学位授予时间：2020年3月\n" +//时间来源评审完成的日期
                            "特发此证，以资鼓励。")
                    .setFont(contentFont)
                    .setFontSize(smallSize)
                    .setTextAlignment(TextAlignment.LEFT)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);

            // 添加签发单位
            Paragraph 主办方 = new Paragraph(
                    "主办方：上海市学位委员会办公室\n" +
                            "上海工商管理专业学位研究生教育指导委员会\n")
                    .setFont(contentFont)
                    .setFontSize(smallSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);
            Paragraph 承办方 = new Paragraph(
                    "承办方：上海市学位委员会办公室\n" +
                            "上海工商管理专业学位研究生教育指导委员会\n" )
                    .setFont(contentFont)
                    .setFontSize(smallSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);
            Paragraph 日期 = new Paragraph(
                    "二零二二年四月" )
                    .setFont(contentFont)
                    .setFontSize(smallSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);
            // 将所有内容绘制到指定位置
            Paragraph 编号 = new Paragraph(
//                    hashMap.get("code")
                    "编号："+"X123456789"
            )
                    .setFont(contentFont)
                    .setFontSize(smallSize)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE);


            document.showTextAligned(获奖段落,
                    x, y - 50,
                    1,//pageNumber这个参数指代放在第几页
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

            document.showTextAligned(奖项, x, y - 120, 1,
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

            document.showTextAligned(指导教师, x - 100, y - 180, 1,
                    TextAlignment.LEFT, VerticalAlignment.MIDDLE, 0);

            document.showTextAligned(主办方, x, y - 280, 1,
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);
            document.showTextAligned(承办方, x, y - 380, 1,
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

            document.showTextAligned(日期, x, y - 420, 1,
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

            document.showTextAligned(编号, x, y - 480, 1,
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

            // 关闭文档
            document.close();


            String filename = Constants.RESOURCE_PREFIX + dest;
            return filename;
        }
    }

    @Override
    public TableDataInfo getListForUser(String id, String proId, PageDomain domain, LoginUser loginUser) {
        try {
            ProjectStageMission mission = stageMissionMapper.selectById(id);
            if (mission == null) {
                return OtherUtil.tableError("该任务不存在，请检查id是否正确");
            }

            ObjectMapper objectMapper = new ObjectMapper();
            Long userId = null;
            ProjectUser projectUser = new ProjectUser();
            /**
             * 第一阶段：获取数据库数据
             */
            //获取清单列表（完成）
            List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                    .stream()
                    .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                    .collect(Collectors.toList());
            //判断角色，获取权限
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId().equals(1L) || role.getRoleId().equals(2L)
                            || role.getRoleId().equals(103L) || role.getRoleId().equals(101L));
            if (isUnauthorizedRole) {
                projectUser = userMapper.selectOne(new LambdaQueryWrapper<ProjectUser>()
                        .eq(ProjectUser::getUserId, loginUser.getUserId())
                        .eq(ProjectUser::getProId, proId)
                        .eq(ProjectUser::getStatus, "0")
                        .eq(ProjectUser::getDelFlag, "0")
                );
                if (projectUser == null) {
                    throw new ServiceException("您没有权限查看此任务", HttpStatus.NOT_FOUND);
                }
                userId = loginUser.getUserId();
            }
            //获取任务的成果提交量
            List<ProjectResultByUserVO> resultList = resultMapper.selectListByUserOrTeacher(
                    id, proId, userId, projectUser.getTeacherName()
            );
            Map<String, List<ProjectResultByUserVO>> resultListMap = resultList.stream()
                    .collect(Collectors.groupingBy(ProjectResultByUserVO::getStageId));
            //获取任务人员列表
            List<StageUserByMission> userByMissions = stageUserMapper.selectListForList(proId, userId);
            Map<String, List<StageUserByMission>> missionMap = userByMissions.stream()
                    .collect(Collectors.groupingBy(StageUserByMission::getMissionId));
            //获取当前任务的全部人员信息
            Map<String, List<StageUserByMission>> collect = Optional.ofNullable(missionMap.get(id))
                    .filter(CollectionUtils::isNotEmpty)
                    .map(userList -> userList.stream()
                            .collect(Collectors.groupingBy(StageUserByMission::getTeacherName)))
                    .orElse(Collections.emptyMap());

            /**
             * 第2阶段：处理数据
             */
            ArrayList<AchievementsStatisticsVO> vos = new ArrayList<>();
            checkDTOs.forEach(checkDTO -> {
                collect.forEach((teacherName, userList) -> {
                    AchievementsStatisticsVO vo = new AchievementsStatisticsVO();
                    vo.setName(checkDTO.getContent());
                    vo.setEndTime(checkDTO.getEndTime());
                    List<ProjectResultByUserVO> projectResultByUserVOS = resultListMap.get(checkDTO.getId());
                    if (CollectionUtils.isEmpty(projectResultByUserVOS)) {
                        vo.setCreateUser(userList.get(0).getUserCodeName());
                        vo.setUserId(userList.get(0).getUserCode());
                        vo.setCreateTime("");
                        vo.setRemark(userList.size() > 1 ? "团队未提交" : "未提交");
                    } else {
                        ProjectResultByUserVO resultVO = projectResultByUserVOS.stream()
                                .filter(result -> teacherName.equals(result.getTeacherName()))
                                .findFirst()
                                .orElse(null);
                        if (resultVO == null) {
                            vo.setCreateUser(userList.get(0).getUserCodeName());
                            vo.setUserId(userList.get(0).getUserCode());
                            vo.setCreateTime("");
                            vo.setRemark(userList.size() > 1 ? "团队未提交" : "未提交");
                        } else {
                            StageUserByMission user = userList.stream()
                                    .filter(result -> resultVO.getCreateUser().equals(result.getUserCode()))
                                    .findFirst()
                                    .orElse(null);
                            ProjectIndexFileDTO indexFileDTO = new ProjectIndexFileDTO();
                            BeanUtils.copyProperties(resultVO, indexFileDTO);
                            indexFileDTO.setFullurl(UrlUtils.getUrl() + indexFileDTO.getUrl());
                            vo.setInformation(indexFileDTO);
                            vo.setCreateUser(user == null ? "" : user.getUserCodeName());//显示的不是人名
                            vo.setUserId(user == null ? "" : user.getUserCode());
                            vo.setCreateTime(DateUtils.dateToString(resultVO.getCreateTime(), DateUtils.YYYY_MM_DD));
                            vo.setRemark(userList.size() > 1 ? "团队已提交" : "已提交");
                        }
                    }
                    vos.add(vo);
                });
            });


            /**
             *3、填写数据
             */
            vos.sort(Comparator.comparing(vo -> vo.getInformation() == null ? 0 : 1));
            List<AchievementsStatisticsVO> vos1 = OtherUtil.startPage(vos, domain.getPageNum(), domain.getPageSize());

            return OtherUtil.tableSuccess2(vos1, vos.size());
        } catch (Exception e) {
            log.error(e.getMessage());
            return OtherUtil.tableError(e.getMessage());
        }

    }

    @Override
    public AjaxResult briefById(String id, Long userId) {
        ProjectStageMission mission = stageMissionMapper.selectById(id);
        if (mission != null) {
            hrefUpdate(mission, userId);
            StageMissionVO stageMissionVO = new StageMissionVO();
            BeanUtils.copyProperties(mission, stageMissionVO);
            List<FileLabelsDTO> labelsDTOS = missionLabelsMapper.selectByMissionId(id);
            stageMissionVO.setLabelList(labelsDTOS);
            ObjectMapper objectMapper = new ObjectMapper();

            List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                    .stream()
                    .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                    .collect(Collectors.toList());

            stageMissionVO.setCheckLists(checkDTOs);
            stageMissionVO.setInformations(getList(mission.getInformation()));
            stageMissionVO.setTools(mission.getTool());//原始的 getList(mission.getTool())
            QueryWrapper<ProjectResult> wrapper = new QueryWrapper<>();
            wrapper.eq("pro_id", stageMissionVO.getStageId());
            wrapper.eq("del_flag", "0");
            wrapper.eq("mission_id", id);
            wrapper.eq("create_user", userId);
            List<ProjectResult> list = resultMapper.selectList(wrapper);
//            stageMissionVO.setResultList(list);
            //补充学生列表
            List<UserVO> userList = userMapper.getStageUser(mission.getId());
            stageMissionVO.setUserList(userList);
            //查找成果列表
            List<ProjectCheckDTO> checkLists = stageMissionVO.getCheckLists();
            if (checkLists != null && checkLists.size() > 0) {
                // 提前构建 stageId -> ProjectResult 映射表
                Map<String, ProjectResult> resultMap = Optional.ofNullable(list)
                        .orElse(Collections.emptyList())
                        .stream()
                        .collect(Collectors.toMap(ProjectResult::getStageId, result -> result));
                for (ProjectCheckDTO checkList : checkLists) {
                    // 从 map 中安全获取对应成果
                    ProjectResult projectResult = resultMap.get(checkList.getId());
                    if (projectResult != null) {
                        ProjectIndexFileDTO indexFileDTO = new ProjectIndexFileDTO();
                        BeanUtils.copyProperties(projectResult, indexFileDTO);
                        indexFileDTO.setFullurl(UrlUtils.getUrl() + indexFileDTO.getUrl());
                        checkList.setInformation(indexFileDTO);
                        checkList.setIsSubmit(true);
                        checkList.setSubmitTime(DateUtils.dateToString(projectResult.getCreateTime(), DateUtils.YYYY_MM_DD));
                    }
                }
            }


            return AjaxResult.success(stageMissionVO);
        }
        return AjaxResult.error("编号错误，未查询到任务");
    }

    @Override
    public TableDataInfo adminListByProId(ProjectResultDTO dto, LoginUser loginUser) {
        try {
            Project project = projectMapper.selectById(dto.getId());
            if (project == null) {
                return OtherUtil.tableError("活动不存在");
            }
            //添加限制，只能超管，创建者，负责人能看到列表
            boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                    .noneMatch(role -> role.getRoleId() != 1L && role.getRoleId() != 2L);
            if (!isUnauthorizedRole) {
                if (!String.valueOf(loginUser.getUserId()).equals(project.getCreateUser())) {
                    Long teacherId = teacherMapper.selectCount(new QueryWrapper<ProjectTeacher>()
                            .eq("tech_id", loginUser.getUserId())
                            .eq("pro_id", project.getId())
                            .eq("del_flag", "0"));
                    if (teacherId == 0) {
                        throw new ServiceException("您无权限访问", HttpStatus.ACCEPTED);
                    }
                }
            }
            //获取可见的任务
            startPage(dto.getPageDomain());
            List<ProjectStageMission> missions = stageMissionMapper.selectLists(dto, null);
            TableDataInfo dataTable = OtherUtil.tableSuccess(missions);
            List<ProjectStageMissionVO> copy = OtherUtil.copy(dataTable.getRows(), ProjectStageMissionVO.class);
            if (copy != null && !copy.isEmpty()) {
                dataTable.setRows(copy);
            }
            return dataTable;
        } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException
                e) {
            log.error("查询失败：" + e.getMessage());
            TableDataInfo error = OtherUtil.tableError(e.getMessage());
            return error;
        }
    }

    @Override
    public List<ProjectStageMissionVO> selectEvaluateList(String userid, String projectId, LoginUser loginUser) {
        try {
            // 获取项目阶段任务
            List<ProjectStageMission> missions = getProjectStageMissions(userid, projectId, loginUser);
            if (CollectionUtils.isEmpty(missions)) {
                return new ArrayList<>();
            }
            List<ProjectStageMissionVO> copy = OtherUtil.copy(missions, ProjectStageMissionVO.class);

            return copy;
        } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException
                e) {
            log.error("查询失败：" + e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 获取项目阶段任务列表
     *
     * @param userid
     * @param projectId
     * @param loginUser
     * @return
     */
    private List<ProjectStageMission> getProjectStageMissions(String userid, String projectId, LoginUser loginUser) {
        Project project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ServiceException("活动不存在", HttpStatus.NOT_FOUND);
        }
        //添加限制，不是教师，不是超管的只能见自己参与的任务
        Long userId = Long.valueOf(userid);
        LambdaQueryWrapper<ProjectTeacher> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProjectTeacher::getProId, projectId);
        wrapper.eq(ProjectTeacher::getTechId, loginUser.getUserId());
        List<ProjectTeacher> projectTeachers = teacherMapper.selectList(wrapper);

        boolean isUnauthorizedRole = loginUser.getUser().getRoles().stream()
                .noneMatch(role -> role.getRoleId() != 1L && role.getRoleId() != 2L);
        if ((projectTeachers == null || projectTeachers.isEmpty()) && !isUnauthorizedRole &&
                !project.getCreateUser().equals(String.valueOf(loginUser.getUserId()))) {
            userId = loginUser.getUserId();
        }

        //获取可见的任务
        ProjectResultDTO dto = new ProjectResultDTO();
        dto.setId(projectId);
        List<ProjectStageMission> missions = stageMissionMapper.selectLists(dto, userId);
        return missions;
    }

    @Override
    public AjaxResult selectStageList(String userId, String stageId, LoginUser loginUser) {
        LambdaQueryWrapper<ProjectStageUser> lqw = new LambdaQueryWrapper<>();
        lqw.and(lqw1 -> lqw1.eq(ProjectStageUser::getUserId, userId).or().eq(ProjectStageUser::getUserId, "All"));
        lqw.eq(ProjectStageUser::getMissionId, stageId);
        lqw.eq(ProjectStageUser::getDelFlag, "0");
        //判断学员是否参加这个概览
        List<ProjectStageUser> projectStageUsers = stageUserMapper.selectList(lqw);
        if (CollectionUtils.isEmpty(projectStageUsers)) {
            logger.error("学员信息：" + userId + "未查询到参与该概览信息，概览编号：" + stageId +
                    "，查询人：" + loginUser.getUserId() + "|" + loginUser.getUser().getNickName());
            return AjaxResult.error("该学员未查询到参与该概览信息，请与管理员联系确定");
        }
        //获取概览信息
        ProjectStageMission mission = stageMissionMapper.selectById(stageId);
        if (mission != null) {
            ObjectMapper objectMapper = new ObjectMapper();
            //处理任务清单结构
            List<ProjectCheckDTO> checkDTOs = ((List<Map<String, Object>>) getList(mission.getCheckList()))
                    .stream()
                    .map(map -> objectMapper.convertValue(map, ProjectCheckDTO.class))
                    .collect(Collectors.toList());

            //查找成果列表
            QueryWrapper<ProjectResult> wrapper = new QueryWrapper<>();
            wrapper.eq("pro_id", mission.getStageId());
            wrapper.eq("del_flag", "0");
            wrapper.eq("mission_id", stageId);
            wrapper.eq("create_user", userId);
            List<ProjectResult> list = resultMapper.selectList(wrapper);
            List<ProjectCheckDTO> checkLists = checkDTOs;
            if (checkLists != null && checkLists.size() > 0) {
                // 提前构建 stageId -> ProjectResult 映射表
                Map<String, ProjectResult> resultMap = Optional.ofNullable(list)
                        .orElse(Collections.emptyList())
                        .stream()
                        .collect(Collectors.toMap(ProjectResult::getStageId, result -> result));
                for (ProjectCheckDTO checkList : checkLists) {
                    // 从 map 中安全获取对应成果
                    ProjectResult projectResult = resultMap.get(checkList.getId());
                    if (projectResult != null) {
                        ProjectExcellent projectExcellent = excellentMapper.selectOne(new LambdaQueryWrapper<ProjectExcellent>()
                                .eq(ProjectExcellent::getResultId, projectResult.getId()));
                        checkList.setIsExcellent(projectExcellent != null ? true : false);
                        ProjectIndexFileDTO indexFileDTO = new ProjectIndexFileDTO();
                        BeanUtils.copyProperties(projectResult, indexFileDTO);
                        indexFileDTO.setFullurl(UrlUtils.getUrl() + indexFileDTO.getUrl());
                        checkList.setInformation(indexFileDTO);
                        checkList.setIsSubmit(true);
                        checkList.setSubmitTime(DateUtils.dateToString(projectResult.getCreateTime(), DateUtils.YYYY_MM_DD));
                    }
                }
            }
            return AjaxResult.success(checkLists);
        } else {
            List<ProjectCheckDTO> checkLists = new ArrayList<>();
            return AjaxResult.success(checkLists);
        }
    }

    @Override
    public List<ProjectStageMission> selectMissionList(String userId, String projectId, LoginUser loginUser) {
        List<ProjectStageMission> missions = getProjectStageMissions(userId, projectId, loginUser);
        if (CollectionUtils.isEmpty(missions)) {
            return new ArrayList<>();
        }
        return missions;
    }

//    public String getUrl() {
//        HttpServletRequest request = ServletUtils.getRequest();
//        return getDomain(request);
//    }
//
//    public static String getDomain(HttpServletRequest request) {
//        StringBuffer url = request.getRequestURL();
//        String contextPath = request.getServletContext().getContextPath();
//        return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
//    }

    private void hrefUpdate(ProjectStageMission project2, Long userId) {
        try {
            if (userId != null & project2.getTool() != null) {
                QueryWrapper<Project> wrapper = new QueryWrapper<>();
                wrapper.eq("id", project2.getStageId());
                Project project = projectMapper.selectOne(wrapper);
                LoginUser loginUser = new LoginUser();
                loginUser.setUserId(userId);
                String extracted = OtherUtil.extracted(project2.getTool(), loginUser, project.getId(), project.getProType());
                project2.setTool(extracted);
            }

        } catch (Exception e) {
            log.error("知网解析失败:" + e.getMessage());
            throw new ServiceException(e.getMessage(), HttpStatus.ACCEPTED);
        }

    }


    private double getDouble(List<ProjectCheckDTO> list, Double 数量) {
        return list != null && list.size() != 0 ? (数量 / list.size() * 100) : 0;
    }

    private double getDouble(Double 总数, Double 数量) {
        return 总数 != 0.0 ? (数量 / 总数 * 100) : 0;
    }

    //
    private Map<String, Object> newStatistic(Map<String, Object> map, String key, Object 数量, Object 占比, String type) {
        if (key == null && 数量 == null && type == null & 占比 == null) {
            map.put(横向, new LinkedHashMap<>());
            map.put(纵向, new LinkedHashMap<>());
            return map;
        }
        Map<String, Object> hashMap2 = (Map<String, Object>) map.get(type);
        HashMap<String, Object> map1 = new LinkedHashMap<>();
        map1.put("数量", 数量);
        if (type.equals(横向)) {
            map1.put("占比", String.format("%.2f", 占比) + " %");
        }
        hashMap2.put(key, map1);
        map.put(type, hashMap2);
        return map;
    }
}
